import collections
import copy
import uuid
from datetime import datetime

import pandas as pd

from server.pao_python.pao.data import (dataframe_to_list, date_to_string,
                                        process_db, string_to_date)
from server.pao_python.pao.service.data.mongo_db import (C, F, MongoFilter,
                                                         MongoService, N,
                                                         as_date)

from ...models.financial_manage import (FinancialAccount, FinancialBook,
                                        FinancialCharge, FinancialEntry,
                                        FinancialRecord,
                                        FinancialSetSubjectItem,
                                        FinancialSubject, FinancialVoucher)
from ...service.app.my_order import OrderStatus, RecordStatus
from ...service.app.service_detail import ServiceProductDetailService
from ...service.buss_mis.operation_record import (OperationRecordObject,
                                                  OperationRecordService,
                                                  OperationRecordType)
from ...service.buss_pub.bill_manage import (BillManageService, OperationType,
                                             Status, TypeId)
from ...service.common import (SerialNumberType, execute_python, find_data,
                               get_current_user_id, get_info,
                               get_serial_number)
from ...service.mongo_bill_service import MongoBillFilter
from .my_order import ThirdPartPayStatus
from ...service.buss_pub.message_manage import MessageManageService


'''
@Description: In User Settings Edit
@Author: your name
@Date: 2019-09-25 09:48:29
@LastEditTime: 2019-09-25 09:48:29
@LastEditors: your name
'''
'''
说明
 1、app确认订单服务
'''


class ComfirmOrderService(MongoService):
    balance = 0
    account_id = ''
    amount = 0

    def __init__(self, db_addr, db_port, db_name, db_user, db_pwd, inital_password, session):
        self.db_addr = db_addr
        self.db_port = db_port
        self.db_name = db_name
        self.db_user = db_user
        self.db_pwd = db_pwd
        self.inital_password = inital_password
        self.session = session
        self.account = {
            'balance': 0,
            'account_id': '',
        }
        self.bill_manage_server = BillManageService(
            self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd, self.inital_password, self.session)
        self.service_product_detail_service = ServiceProductDetailService(
            self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd, self.inital_password, self.session)
        self.OperationRecordService = OperationRecordService(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)
        self.MessageManageService = MessageManageService(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)

    def get_all_product(self, condition):
        keys = ['id']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id']))\
            .lookup_bill('PT_Service_Order', 'id', 'detail.product_id', 'order_info')\
            .add_fields({'pay_count': self.ao.size('$order_info'), })\
            .project({'_id': 0, 'order_info._id': 0})
        res = self.query(_filter, 'PT_Service_Product')
        porduct_item_list = []
        try:
            if res:
                product_queue = collections.deque()
                product_queue.append(res[0])
                while len(product_queue) != 0:
                    res_f = product_queue.popleft()
                    if res_f.get('service_product'):
                        for product_id_list in res_f.get('service_product'):
                            if product_id_list.get("product_id"):
                                res_child = self.service_product_detail_service.get_children_tree(
                                    product_id_list.get("product_id"))
                                if res_child:
                                    if res_child[0].get('service_product'):
                                        product_queue.append(res_child[0])
                                    else:
                                        if product_id_list.get("remaining_times"):
                                            res_child[0]['remaining_times'] = product_id_list.get(
                                                "remaining_times")
                                        else:
                                            res_child[0]['remaining_times'] = 1
                                        porduct_item_list.append(res_child[0])
                            else:
                                porduct_item_list.append(res_f)
                    else:
                        porduct_item_list.append(res_f)
                for product_item in porduct_item_list:
                    product_item_price = 0
                    if product_item.get('valuation_formula') and product_item.get('service_option'):
                        if product_item.get('valuation_formula').get('formula'):
                            product_item_price = execute_python(product_item.get('valuation_formula')[0].get(
                                'formula'), product_item.get('service_option'), 'name', 'option_value')
                            product_item['valuation_amount'] = product_item_price * \
                                int(product_item['remaining_times'])
        except Exception as e:
            print(e)
        return porduct_item_list

    def get_purchaser_detail(self):
        '''获取购买者信息'''
        data = {}
        person_id = get_current_user_id(self.session)
        _filter_user = MongoBillFilter()
        _filter_user.match_bill((C('id') == person_id)).project({'_id': 0})
        res_user = self.query(_filter_user, 'PT_User')
        if res_user:
            if res_user[0]['personnel_info']:
                data['personnel_info'] = res_user[0]['personnel_info']
            if not res_user[0]['personnel_info'].get('address') and res_user[0].get('address'):
                data['personnel_info']['address'] = res_user[0]['address']
            else:
                data['personnel_info']['address'] = []
            if res_user[0]['personnel_info'].get('name'):
                pass
            elif res_user[0].get('name'):
                data['personnel_info']['name'] = res_user[0].get('name')
            else:
                data['personnel_info']['name'] = []

        return data

    def change_trade_status(self, status):
        '''修改付款状态'''
        status = None
        if status == '已付款':
            status = ThirdPartPayStatus.payed.value
        elif status == '未付款':
            status = ThirdPartPayStatus.unpay.value
        else:
            return False
        bill_id = self.bill_manage_server.add_bill(OperationType.update.value,
                                                   TypeId.serviceOrder.value, {'id': '', 'pay_status': status}, 'PT_Service_Record')
        if bill_id:
            res = 'Success'

        return res

    def _create_product_order(self, data, is_paying_first, pay_status=ThirdPartPayStatus.unpay.value):
        '''创建订单（服务订单表）'''
        '''
        data: dict 订单数据
        data:{
            'service_product_id'：产品id,
            'count':产品数量,
            'name':产品名,
            'appointment_time'
        }
        is_paying_first : 0 or 1  是否先付费
        pay_status 支付状态
        return res
        '''
        order_data = {}
        res = "Fail"
        order_code = ''

        def process_func(db):
            nonlocal order_code
            order_code = get_serial_number(db, SerialNumberType.order.value)
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        if 'name' in data.keys():
            person_id = data.get("name")
        else:
            person_id = get_current_user_id(self.session)
        order_data['purchaser_id'] = person_id
        order_data['order_code'] = order_code
        pro_id = data.get("service_product_id")
        count = data.get('count')
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == pro_id)).project({'_id': 0})
        res_product = self.page_query(
            _filter, 'PT_Service_Product', None, None)
        try:
            if res_product['result']:
                order_data['service_provider_id'] = res_product['result'][0].get(
                    'organization_id')
                order_data['organization_id'] = res_product['result'][0].get(
                    'organization_id')
            else:
                order_data['service_provider_id'] = ''
            order_data['order_date'] = datetime.now()
            product_list = self.get_all_product({'id': pro_id})
            new_product_list = []
            record_list = []
            if product_list:
                for product in product_list:
                    pro_dict = {}
                    pro_dict['product_id'] = product.get('id')
                    pro_dict['product_name'] = product.get('name')
                    pro_dict['valuation_formula'] = product.get(
                        'valuation_formula')
                    pro_dict['service_option'] = product.get('service_option')
                    pro_dict['contract_terms'] = product.get(
                        'additonal_contract_terms')
                    pro_dict['remark'] = product.get('remark')
                    # 添加是否可分派
                    pro_dict['is_assignable'] = product.get('is_assignable')
                    pro_dict['count'] = count
                    pro_dict['all_times'] = product.get('remaining_times')
                    new_product_list.append(pro_dict)
            order_data['pay_state'] = pay_status
            if 'order_state' in data.keys():
                order_data['status'] = data.get('order_state')
            else:
                order_data['status'] = OrderStatus.order_unserved.value
            order_data['detail'] = new_product_list
            order_new_data = get_info(order_data, self.session)
            order_new_data['is_paying_first'] = is_paying_first
            # 补充原有的数据
            origin_data = {}
            origin_data['product_id'] = res_product['result'][0].get('id')
            origin_data['product_name'] = res_product['result'][0].get('name')
            order_new_data['origin_product'] = origin_data
            # 补充
            if 'address' in data.keys():
                order_new_data['address'] = data.get('address')
            # order_new_data['order_state'] = data.get('order_state')
            if 'amout' in data.keys():
                order_new_data['amout'] = data.get('amout')
            if 'comment' in data.keys():
                order_new_data['comment'] = data.get('comment')
            if 'buy_type' in data.keys():
                order_new_data['buy_type'] = data.get('buy_type')
            if 'appointment_time' in data.keys():
                order_new_data['buy_type'] = data.get('appointment_time')

            if is_paying_first == '1':
                for product in product_list:
                    record_dict = {}
                    record_dict['order_id'] = order_new_data.get('id')
                    record_dict['service_product_id'] = product.get('id')
                    record_dict['start_date'] = order_new_data.get(
                        'create_date')
                    record_dict['end_date'] = order_new_data.get('create_date')
                    record_dict['is_virtual'] = '1'
                    record_dict['status'] = RecordStatus.service_completed.value
                    record_dict['valuation_amount'] = product.get(
                        'valuation_amount')
                    record_dict['content'] = product.get('introduce')
                    if product.get('service_option'):
                        option_list = []
                        for option in product.get('service_option'):
                            if option.get('option_type') == 'service_before':
                                option_list.append(option)
                        record_dict['service_option'] = option_list
                    record_list.append(record_dict)
                return {'order_data': order_new_data, 'record_data': record_list}
            else:
                return {'order_data': order_new_data, 'record_data': []}

        except Exception as e:
            print(e)
        return res

    def create_product_order(self, data, is_paying_first='1', pay_status=ThirdPartPayStatus.unpay.value):
        '''
        data: list or dict 订单数据
        is_paying_first : 0 or 1  是否先付费
        return res
        '''
        res = "Fail"
        result = {}
        if type(data) == list:
            for per_data in data:
                result = self._create_product_order(
                    per_data, is_paying_first, pay_status)
                if result.get('order_data') and result.get('record_data'):
                    bill_id = self.bill_manage_server.add_bill(OperationType.add.value,
                                                               TypeId.serviceOrder.value, [result.get('order_data'), result.get('record_data')], ['PT_Service_Order', 'PT_Service_Record'])
                    if bill_id:
                        res = 'Success'
                elif result.get('order_data') and (not result.get('record_data')):
                    bill_id = self.bill_manage_server.add_bill(OperationType.add.value,
                                                               TypeId.serviceOrder.value, result.get('order_data'), 'PT_Service_Order')
                    if bill_id:
                        res = 'Success'
        else:
            result = self._create_product_order(
                data, is_paying_first, pay_status)
            if result.get('order_data') and result.get('record_data'):
                bill_id = self.bill_manage_server.add_bill(OperationType.add.value,
                                                           TypeId.serviceOrder.value, [result.get('order_data'), result.get('record_data')], ['PT_Service_Order', 'PT_Service_Record'])
                if bill_id:
                    res = 'Success'
            elif result.get('order_data') and (not result.get('record_data')):
                bill_id = self.bill_manage_server.add_bill(OperationType.add.value,
                                                           TypeId.serviceOrder.value, result.get('order_data'), 'PT_Service_Order')
            if bill_id:
                res = 'Success'
        # 添加使用记录
        if res == 'Success':
            # 插入一个消息提醒
            self.MessageManageService.add_new_message({
                # 购买信息标识
                "business_type": 'service_order',
                # 业务ID
                "business_id": result['order_data']['id']
            })
            real_account_data = OperationRecordObject(
                get_current_user_id(self.session), OperationRecordType.order, result['order_data']['id'], result['order_data']['origin_product']['product_name'])
            self.OperationRecordService.insert_record(
                real_account_data.to_dict())
        return res

    def batch_create_order(self, data, price, is_paying_first='0'):
        person_id = get_current_user_id(self.session)
        if 'name' in data.keys():
            person_id = data.get("name")
        res_account = []
        # 查询该长者的补贴账户
        if data.get("buy_type") == '补贴账户':
            _filter_account = MongoBillFilter()
            _filter_account.match_bill((C('user_id') == person_id) & (
                C('account_type') == '补贴账户')).project({'_id': 0})
            res_account = self.page_query(
                _filter_account, 'PT_Financial_Account', None, None)
            # 判断该长者是否有补贴账户
            if len(res_account['result']) <= 0:
                return '该用户没有补贴账户'
        else:
            _filter_account = MongoBillFilter()
            _filter_account.match_bill((C('user_id') == person_id) & (
                C('account_type') == '慈善账户')).project({'_id': 0})
            res_account = self.page_query(
                _filter_account, 'PT_Financial_Account', None, None)
        self.account_id = res_account['result'][0]['id']
        self.amount = res_account['result'][0]['balance']

        # price = 0
        # # 服务产品的总价格需要服务选项累加起来
        # if res_product['result']:
        #     if res_product['result'][0]['is_service_item'] == 'false':
        #         pruduct_detail = self.service_product_detail_service.get_service_product_package_detail(
        #             {'id': pro_id})
        #         if len(pruduct_detail) > 0 and 'total_price' in pruduct_detail[0]:
        #             price = pruduct_detail[0].get(
        #                 'total_price')
        #         else:
        #             price = float(res_product['result'][0]['service_package_price'])
        #     else:
        #         for opn in res_product['result'][0]['service_option']:
        #             price += float(opn['option_value'])
        if type(price) == str:
            price = float(price)
        # 判断余额是否充足
        if res_account['result'][0]['balance'] < price:
            return '账户余额不足'
        self.balance = price
        res = self.create_product_order(
            data, is_paying_first, ThirdPartPayStatus.payed.value)
        if res == 'Success':
            self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.financial.value, {'id': self.account_id, 'balance': self.amount-self.balance}, 'PT_Financial_Account')
            self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.financial.value, {'balance': self.amount-self.balance, 'amount': (self.amount) * (-1), 'abstract': '服务购买', 'date': datetime.now(), 'remark': '', 'account_id': self.account_id}, 'PT_Financial_Account_Record')
        return res

    def update_reserve_service(self, data):
        '''新增修改预约服务'''
        res = 'Fail'
        datas = []
        bill_id = ''
        _filter_provider = MongoBillFilter()
        _filter_provider.match_bill(
            (C('id') == data['service_provider_id'])).project({'_id': 0})
        res_provider = self.query(_filter_provider, 'PT_User')
        _filter_product = MongoBillFilter()
        _filter_product.match_bill(
            (C('id') == data['service_product_id'])).project({'_id': 0})
        res_product = self.query(_filter_product, 'PT_Service_Product')
        if 'id' not in list(data.keys()):
            # 如果按照类型预服务
            if 'personnel_classification' in list(data.keys()):
                _filter_reserve = MongoBillFilter()
                _filter_reserve.match_bill(
                    (C('personnel_classification') == data['personnel_classification'])).project({'_id': 0})
                res_reserve = self.query(_filter_reserve, 'PT_Reserve_Service')
                for reserve in res_reserve:
                    self.bill_manage_server.add_bill(OperationType.delete.value,
                                                     TypeId.assessmentProject.value, reserve['id'], 'PT_Reserve_Service')
                _filter_user = MongoBillFilter()
                _filter_user.match_bill(
                    (C('personnel_info.personnel_classification') == data['personnel_classification'])).project({'_id': 0})
                res_user = self.query(_filter_user, 'PT_User')
                for user in res_user:
                    data_new = data.copy()
                    data_new['name'] = user['id']
                    data_new['user_name'] = user['name']
                    data_new['provider_name'] = res_provider[0]['name']
                    data_new['provider_id'] = res_provider[0]['id']
                    data_new['product_name'] = res_product[0]['name']
                    data_new['product_id'] = res_product[0]['id']
                    datas.append(get_info(data_new, self.session))
                bill_id = self.bill_manage_server.add_bill(
                    OperationType.add.value, TypeId.reserveService.value, datas, ['PT_Reserve_Service'])
            else:
                _filter_reserve = MongoBillFilter()
                _filter_reserve.match_bill(
                    (C('name') == data['name'])).project({'_id': 0})
                res_reserve = self.query(_filter_reserve, 'PT_Reserve_Service')
                if len(res_reserve) > 0:
                    data_new = data.copy()
                    data_new['id'] = res_reserve[0]['id']
                    data_new['name'] = res_reserve[0]['name']
                    data_new['user_name'] = res_reserve[0]['user_name']
                    data_new['provider_name'] = res_reserve[0]['name']
                    data_new['provider_id'] = res_reserve[0]['id']
                    data_new['product_name'] = res_reserve[0]['name']
                    data_new['product_id'] = res_reserve[0]['id']
                    datas.append(get_info(data_new, self.session))
                    bill_id = self.bill_manage_server.add_bill(
                        OperationType.add.value, TypeId.reserveService.value, datas, ['PT_Reserve_Service'])
                else:
                    _filter_user = MongoBillFilter()
                    _filter_user.match_bill(
                        (C('id') == data['name'])).project({'_id': 0})
                    res_user = self.query(_filter_user, 'PT_User')
                    data_new = data.copy()
                    data_new['name'] = res_user[0]['id']
                    data_new['user_name'] = res_user[0]['name']
                    data_new['provider_name'] = res_provider[0]['name']
                    data_new['provider_id'] = res_provider[0]['id']
                    data_new['product_name'] = res_product[0]['name']
                    data_new['product_id'] = res_product[0]['id']
                    datas.append(get_info(data_new, self.session))
                    bill_id = self.bill_manage_server.add_bill(
                        OperationType.add.value, TypeId.reserveService.value, datas, ['PT_Reserve_Service'])
        else:
            _filter_user = MongoBillFilter()
            _filter_user.match_bill(
                (C('id') == data['name'])).project({'_id': 0})
            res_user = self.query(_filter_user, 'PT_User')
            data_new = data.copy()
            data_new['name'] = res_user[0]['id']
            data_new['user_name'] = res_user[0]['name']
            data_new['provider_name'] = res_provider[0]['name']
            data_new['provider_id'] = res_provider[0]['id']
            data_new['product_name'] = res_product[0]['name']
            data_new['product_id'] = res_product[0]['id']
            datas.append(get_info(data_new, self.session))
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.reserveService.value, datas, ['PT_Reserve_Service'])
        if bill_id:
            res = 'Success'
        return res

    def get_reserve_service(self, condition, page=None, count=None):
        '''获取服务预约'''
        keys = ['id', 'user_name', 'provider_name', 'product_name']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id']) & (C('user_name') == values['user_name']) & (
            C('provider_name') == values['provider_name']) & (
            C('product_name') == values['product_name']))\
            .project({'_id': 0})
        res = self.page_query(_filter, 'PT_Reserve_Service', page, count)
        return res

    def delete_reserve_service(self, condition):
        '''删除预定服务'''
        res = 'fail'

        def process_func(db):
            nonlocal res
            ids = []
            if isinstance(condition, str):
                ids.append(condition)
            else:
                ids = condition
            for Reserve_Service_id in ids:
                # 查询被删除的数据信息
                data = find_data(db, 'PT_Reserve_Service', {
                    'id': Reserve_Service_id, 'bill_status': 'valid'})
                if len(data) > 0:
                    self.bill_manage_server.add_bill(OperationType.delete.value,
                                                     TypeId.reserveService.value, data[0], 'PT_Reserve_Service')
            res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        return res

    def one_key_order(self):
        _filter = MongoBillFilter()
        _filter.match_bill().project({'_id': 0})
        res = self.query(_filter, 'PT_Reserve_Service')
        ret = self.create_product_order(res, is_paying_first='0')
        return ret


#############################################################

    # def add_comfirm_order(self, data):
    #     '''创建订单（服务订单表）'''
    #     order_data = {}
    #     res = "Fail"
    #     person_id = get_current_user_id(self.session)
    #     pk_id = data.get("service_pack_id")
    #     _filter = MongoFilter()
    #     _filter.match((C('bill_status') == 'valid') & (
    #         C('id') == pk_id)).project({'_id': 0})
    #     res_pk = self.page_query(
    #         _filter, 'PT_Service_Item_Package', None, None)
    #     try:
    #         if res_pk['result']:
    #             order_data['service_provider_id'] = res_pk['result'][0].get(
    #                 'organization')
    #         else:
    #             order_data['service_provider_id'] = ''
    #         order_data['order_date'] = datetime.datetime.now()
    #         order_data['purchaser_id'] = person_id
    #         service_item = []
    #         service_package_info = self.service_product_detail_service.get_service_package_detail(
    #             pk_id)
    #         if service_package_info:
    #             for key, item in enumerate(service_package_info[0].get('service_item')):
    #                 item_dict = {}
    #                 item_dict['service_item'] = item.get('service_item')
    #                 item_dict['service_type'] = item.get('service_type')
    #                 item_dict['count'] = data.get('count')
    #                 service_options = []
    #                 for option in item.get('service_options'):
    #                     option_dict = {}
    #                     option_dict['id'] = option.get('id')
    #                     if data.get('service_item')[key].get('key'):
    #                         option_dict['value'] = float(
    #                             data.get('service_item')[key].get('value'))
    #                         option_dict['name'] = data.get('service_item')[
    #                             key].get('key').split('-')[0]
    #                     else:
    #                         option_dict['value'] = 0
    #                         option_dict['name'] = ''
    #                     service_options.append(option_dict)
    #                 item_dict['service_options'] = service_options
    #                 service_item.append(item_dict)
    #         else:
    #             return 'no service package'
    #         order_data['service_item'] = service_item
    #         order_data['status'] = OrderStatus.order_unserved.value
    #         bill_id = self.bill_manage_server.add_bill(OperationType.add.value,
    #                                                    TypeId.serviceOrder.value, order_data, 'PT_Service_Order')
    #         if bill_id:
    #             res = 'Success'
    #     except Exception as e:
    #         print(e)
    #     return res
